package com.cfjjc.gz.common.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

/**
 * 字符串辅助类，处理常用的字符串操作
 */

public class StringUtil {

	/**
	 * 缺省的字符串分割符
	 */
	public static String DEFAULT_DELIM = "$*";

    /**
     * 空字符串
     */
    public static final String EMPTY = "";
    
	/**
	 * 私有构造方法，防止类的实例化，因为工具类不需要实例化。
	 */
	private StringUtil() {
	}

	// Empty checks
    //-----------------------------------------------------------------------
    /**
     * <p> 判断某字符串是否为空，为空的标准是 str==null 或 str.length()==0 .</p>
     *
     * <pre>
     * StringUtils.isEmpty(null)      = true
     * StringUtils.isEmpty("")        = true
     * StringUtils.isEmpty(" ")       = false
     * StringUtils.isEmpty("bob")     = false
     * StringUtils.isEmpty("  bob  ") = false
     * </pre>
     *
     * <p>NOTE: This method changed in Lang version 2.0.
     * It no longer trims the CharSequence.
     * That functionality is available in isBlank().</p>
     *
     * @param cs  the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is empty or null
     * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
     */
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * <p>  判断某字符串是否非空，等于 !isEmpty(String str) .</p>
     *
     * <pre>
     * StringUtils.isNotEmpty(null)      = false
     * StringUtils.isNotEmpty("")        = false
     * StringUtils.isNotEmpty(" ")       = true
     * StringUtils.isNotEmpty("bob")     = true
     * StringUtils.isNotEmpty("  bob  ") = true
     * </pre>
     *
     * @param cs  the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is not empty and not null
     * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
     */
    public static boolean isNotEmpty(CharSequence cs) {
        return !StringUtil.isEmpty(cs);
    }

    
    /**
     * <p>去掉字符串两端的控制符(control characters, char <= 32) ,如果变为 null 或 "" ，则返回 "" 
     * <pre>
     * StringUtils.trimToEmpty(null)          = ""
     * StringUtils.trimToEmpty("")            = ""
     * StringUtils.trimToEmpty("     ")       = ""
     * StringUtils.trimToEmpty("abc")         = "abc"
     * StringUtils.trimToEmpty("    abc    ") = "abc"
     * </pre>
     *
     * @param str  the String to be trimmed, may be null
     * @return the trimmed String, or an empty String if {@code null} input
     */
    public static String trimToEmpty(String str) {
        return str == null ? EMPTY : str.trim();
    }
    
	/**
	 * 将字符串数组使用缺省的分隔符合并成一个字符串。
	 * 
	 * @param array
	 *            字符串数组
	 * @return 合并后的字符串
	 */
	public static String join(String[] array) {
		return join(array, DEFAULT_DELIM);
	}

	/**
	 * 将字符串数组使用指定的分隔符合并成一个字符串。
	 * 
	 * @param array
	 *            字符串数组
	 * @param delim
	 *            分隔符，为null的时候使用缺省分割符（逗号）
	 * @return 合并后的字符串
	 */
	public static String join(String[] array, String delim) {
		int length = array.length - 1;
		if (delim == null) {
			delim = DEFAULT_DELIM;
		}
		StringBuffer result = new StringBuffer(length * 8);
		for (int i = 0; i < length; i++) {
			result.append(array[i]);
			result.append(delim);
		}
		result.append(array[length]);
		return result.toString();
	}

	/**
	 * 将字符串使用缺省分割符（逗号）划分的单词数组。
	 * 
	 * @param source
	 *            需要进行划分的原字符串
	 * @return 划分以后的数组，如果source为null的时候返回以source为唯一元素的数组。
	 */
	public static String[] split(String source) {
		return split(source, DEFAULT_DELIM);
	}

	/**
	 * 此方法将给出的字符串source使用delim划分为单词数组。 注意：分隔字符串中每一个<b>(ANY)</b>的字符都作为独立的分割符。<br>
	 * 
	 * @param source
	 *            需要进行划分的原字符串
	 * @param delim
	 *            单词的分隔字符串
	 * @return 划分以后的数组，如果source为null的时候返回以source为唯一元素的数组，
	 *         如果delim为null则使用逗号作为分隔字符串。
	 */
	public static String[] split(String source, String delim) {
		String[] wordLists;
		if (source == null) {
			wordLists = new String[1];
			wordLists[0] = source;
			return wordLists;
		}
		if (delim == null) {
			delim = DEFAULT_DELIM;
		}
		StringTokenizer st = new StringTokenizer(source, delim);

		int total = st.countTokens();
		wordLists = new String[total];
		for (int i = 0; i < total; i++) {
			wordLists[i] = st.nextToken();
		}
		return wordLists;
	}

	/**
	 * 字符串数组中是否包含指定的字符串。 注意：准确的说应该是匹配，而不是包含。<br>
	 * 举个例子：字符串数组"","mofit.com"里<b>不包含</b>"com"，<br>
	 * 但是<b>包含</b>"mofit.com.cn"。
	 * 
	 * @param strings
	 *            字符串数组
	 * @param string
	 *            字符串
	 * @param caseSensitive
	 *            是否大小写敏感
	 * @return 包含时返回true，否则返回false
	 */
	public static boolean contains(String[] strings, String string,
			boolean caseSensitive) {
		for (int i = 0; i < strings.length; i++) {
			if (caseSensitive == true) {
				if (strings[i].equals(string)) {
					return true;
				}
			} else {
				if (strings[i].equalsIgnoreCase(string)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 字符串数组中是否包含指定的字符串。大小写敏感。<br>
	 * 注意：准确的说应该是匹配，而不是包含。<br>
	 * 举个例子：字符串数组"","mofit.com"里<b>不包含</b>"com"，<br>
	 * 但是<b>包含</b>"mofit.com.cn"。
	 * 
	 * @param strings
	 *            字符串数组
	 * @param string
	 *            字符串
	 * @return 包含时返回true，否则返回false
	 */
	public static boolean contains(String[] strings, String string) {
		return contains(strings, string, true);
	}

	/**
	 * 判断指定字符串string在数组strings中左包含的次数<br>
	 * 例如:strings={"001","001001","001002"},string="001", 则返回3
	 * 
	 * @param strings
	 * @param string
	 * @param caseSensitive
	 * @return
	 */
	public static int leftContainsNum(String source, String find) {
		int num = 0;
		String[] strs = source.split(",");
		for (int i = 0; i < strs.length; i++) {
			if (strs[i].indexOf(find) == 0) {
				num++;
			}
		}
		return num;
	}

	/**
	 * 去除左边多余的空格。
	 * 
	 * @param value
	 *            待去左边空格的字符串
	 * @return 去掉左边空格后的字符串
	 */
	public static String trimLeft(String value) {
		String result = value;
		if (result == null) {
			return result;
		}
		char ch[] = result.toCharArray();
		int index = -1;
		for (int i = 0; i < ch.length; i++) {
			if (Character.isWhitespace(ch[i])) {
				index = i;
			} else {
				break;
			}
		}
		if (index != -1) {
			result = result.substring(index + 1);
		}
		return result;
	}

	/**
	 * 去除右边多余的空格。
	 * 
	 * @param value
	 *            待去右边空格的字符串
	 * @return 去掉右边空格后的字符串
	 */
	public static String trimRight(String value) {
		String result = value;
		if (result == null) {
			return result;
		}
		char ch[] = result.toCharArray();
		int endIndex = -1;
		for (int i = ch.length - 1; i > -1; i--) {
			if (Character.isWhitespace(ch[i])) {
				endIndex = i;
			} else {
				break;
			}
		}
		if (endIndex != -1) {
			result = result.substring(0, endIndex);
		}
		return result;
	}

	/**
	 * 得到字符串的字节长度。汉字占两个字节，字母占一个字节
	 * 
	 * @param source
	 *            字符串
	 * @return 字符串的字节长度
	 */
	public static int getLength(String source) {
		if (source == null || source.equals("")) {
			return 0;
		}
		int len = 0;
		for (int i = 0; i < source.length(); i++) {
			char c = source.charAt(i);
			int highByte = c >>> 8;
			len += highByte == 0 ? 1 : 2;
		}
		return len;
	}

	/**
	 * 使用给定的字串替换源字符串中指定的字串。
	 * 
	 * @param mainString
	 *            源字符串
	 * @param oldString
	 *            被替换的字串
	 * @param newString
	 *            替换字串
	 * @return 替换后的字符串
	 */
	public final static String replace(String mainString, String oldString,
			String newString) {
		if (mainString == null) {
			return null;
		}
		int i = mainString.lastIndexOf(oldString);
		if (i < 0) {
			return mainString;
		}
		StringBuffer mainSb = new StringBuffer(mainString);
		while (i >= 0) {
			mainSb.replace(i, i + oldString.length(), newString);
			i = mainString.lastIndexOf(oldString, i - 1);
		}
		return mainSb.toString();
	}

	/**
	 * 将给定的字符串转换为中文GBK编码的字符串。
	 * 
	 * @param str
	 *            输入字符串
	 * @return 经GBK编码后的字符串，如果有异常，则返回原编码字符串
	 */
	public final static String toChinese(final String str) {
		if (null == str || "".equals(str)) {
			return str;
		}
		String retVal = str;
		try {
			retVal = new String(str.getBytes("ISO8859_1"), "GBK");
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		return retVal;
	}

	/**
	 * 将给定的中文GBK编码转换为UNICODE编码的字符串。
	 * 
	 * @param str
	 *            输入字符串
	 * @return 经GBK编码后的字符串，如果有异常，则返回原编码字符串
	 */
	public final static String toUNICODE(final String str) {
		if (null == str || "".equals(str)) {
			return str;
		}
		String retVal = str;
		try {
			retVal = new String(str.getBytes("ZHS16GBK"), "GBK");
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		return retVal;
	}

	/**
	 * 用于字符串显示。将html敏感的尖括号、引号、连接号等用转义符替代。<br>
	 * 建议用法：在接收到客户端传来的字符串时，不进行转换，直接存入数据库；<br>
	 * 在从数据库中取出，传给客户端做html显示时，才转换。
	 * 
	 * @param input
	 *            需要检查的字符串
	 * @return 转化后的字串
	 */
	public final static String convertToHTML(String input) {
		if (null == input || "".equals(input)) {
			return input;
		}

		StringBuffer buf = new StringBuffer();
		char ch = ' ';
		for (int i = 0; i < input.length(); i++) {
			ch = input.charAt(i);
			if (ch == '<') {
				buf.append("&lt;");
			} else if (ch == '>') {
				buf.append("&gt;");
			} else if (ch == '&') {
				buf.append("&amp;");
			} else if (ch == '"') {
				buf.append("&quot;");
			} else if (ch == '\n') {
				buf.append("<BR/>");
			} else if (ch == '\r') {
				buf.append("<BR/>");
			} else {
				buf.append(ch);
			}
		}
		return buf.toString();
	}

	/**
	 * 删除回车换行符
	 * 
	 * @param input
	 * @return
	 */
	public final static String removeReturn(String input) {
		if (null == input || "".equals(input)) {
			return input;
		}

		StringBuffer buf = new StringBuffer();
		char ch = ' ';
		for (int i = 0; i < input.length(); i++) {
			ch = input.charAt(i);
			if (ch == '\n') {
				continue;
			} else if (ch == '\r') {
				continue;
			} else {
				buf.append(ch);
			}
		}
		return buf.toString();
	}

	/**
	 * 定义字符串加密时需要用到的标记字符串
	 */
	private static String ENCRYPT_IN = "YN8K1JOZVURB3MDETS5GPL27AXW`IHQ94C6F0~qwert!@yuiop#$asdfghj%kl^&*zxc vbn(m)_+|{}:\"<>?-=\\[];,./'";

	/**
	 * 定义字符串加密时需要用到的转义字符串
	 */
	private static String ENCRYPT_OUT = "qazwsxcderfvbgtyhnmjuiklop~!@#$%^&*()_+|{ }:\"<>?-=\\[];,./'ABCDE`FGHIJKLMNOPQRSTUVWXYZ0123456789";

	/**
	 * 对给定字符串进行加密操作
	 * 
	 * @param inPass
	 *            待加密的字符串
	 * @return 加密后的字符串
	 */
	public static String encrypt(String inPass) {
		String stringIn = ENCRYPT_IN;
		String stringOut = ENCRYPT_OUT;
		int time1 = Calendar.getInstance().get(Calendar.MINUTE);
		int time2 = Calendar.getInstance().get(Calendar.SECOND);
		int offset = (time1 + time2) % 95;
		String outPass = stringIn.substring(offset, offset + 1);
		stringIn = stringIn + stringIn;
		stringIn = stringIn.substring(offset, offset + 95);
		String temp = "";
		for (int i = 0; i <= inPass.length() - 1; i++) {
			temp = temp + stringOut.charAt(stringIn.indexOf(inPass.charAt(i)));

		}
		outPass = outPass + temp;
		return outPass;
	}

	/**
	 * 对给定字符串进行解密操作
	 * 
	 * @param outPass
	 *            待解密的字符串
	 * @return 解密还原后的字符串
	 */
	public static String decrypt(String outPass) {
		String stringIn = ENCRYPT_IN;
		String stringOut = ENCRYPT_OUT;
		int offset = stringIn.indexOf(outPass.charAt(0));
		stringIn = stringIn + stringIn;
		stringIn = stringIn.substring(offset, offset + 95);
		outPass = outPass.substring(1);
		String inPass = "";
		for (int i = 0; i <= outPass.length() - 1; i++) {
			inPass = inPass
					+ stringIn.charAt(stringOut.indexOf(outPass.charAt(i)));

		}
		return inPass;
	}

	// 指定的字符串累加
	public static String strAdd(String chr, int len) {
		if (len > 0) {
			StringBuffer ret = new StringBuffer(len);
			for (int i = 0; i < len; i++) {
				ret.append(chr);
			}
			return (ret.toString());
		} else {
			return "";
		}
	}

	/**
	 * 给字符串补足到指定的长度，从左边补足chr指定的字符
	 * 
	 * @param source
	 *            源字符串
	 * @param chr
	 *            左边补足的字符
	 * @param len
	 *            最终长度
	 * @return
	 */
	public static String lPad(String source, String chr, int len) {
		int lenleft = len - source.length();
		if (lenleft < 0) {
			lenleft = 0;
		}
		return (strAdd(chr, lenleft) + source);
	}

	/**
	 * 给字符串补足到指定的长度，从右边补足chr指定的字符
	 * 
	 * @param source
	 *            源字符串
	 * @param chr
	 *            右边补足的字符
	 * @param len
	 *            最终长度
	 * @return
	 */
	public static String rPad(String source, String chr, int len) {
		int lenleft = len - source.length();
		if (lenleft < 0) {
			lenleft = 0;
		}
		return (source + strAdd(chr, lenleft));
	}
	
	/**
	 * 根据给定的编码规则，将编码转换成另一种格式，供博思程序接口使用。
	 * <p>
	 * <b>前置条件</b>: 要求原始编码必须满足编码规则
	 * <p>
	 * <b>格式约定</b>：举例说明，若编码为“0010101”，编码规则为“322”，则转换后的编码为“001.01.01"
	 * @param srcFbm 原始编码
	 * @param codeReg 编码规则
	 * @return 转换后的编码
	 */
	public static String getFormatFbm(String srcFbm, String codeReg) {
		
		StringBuffer fbm = new StringBuffer(srcFbm);
		int index = 0;
		for (int i = 0; i < codeReg.length(); i++) {
			int num = Integer.parseInt(codeReg.charAt(i) + "");
			index += num;
			if (srcFbm.length() == index)
				break;
			fbm.insert(index + i, '.');
		}
		return fbm.toString();
	}

	public static void main(String[] args) {
/*		String test = "222,3,4,5,6,76";
		String[] array = StringUtil.split(test, ",");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i]);
		}
		System.out.println();
		test = "222";
		array = StringUtil.split(test, ",");
		for (int i = 0; i < array.length; i++) {
			System.out.println(array[i]);
		}
		test = "222,";
		array = StringUtil.split(test, ",");
		for (int i = 0; i < array.length; i++) {
			System.out.println(array[i]);
		}*/
		/**
		 * String[] test = { "北京", " neusoft.com ", "<out\"OfTax>" }; String
		 * all = join(test, "||");
		 * 
		 * System.out.println("字符串[" + test[0] + "],[" + test[1] + "],[" +
		 * test[2] + "]合并结果：" + all); System.out.println("字符串[" + test[0] +
		 * "],[" + test[1] + "],[" + test[2] + "]是否包含［<out\"oftax>］(区分大小写)：" +
		 * contains(test, "<out\"oftax>")); System.out.println("字符串[" + test[0] +
		 * "],[" + test[1] + "],[" + test[2] + "]是否包含［<out\"oftax>］(不区分大小写)：" +
		 * contains(test, "<out\"oftax>", false)); System.out.println("字符串[" +
		 * all + "]转换为html：" + convertToHTML(all));
		 * 
		 * String en = encrypt(test[2]);
		 * 
		 * System.out.println("字符串[" + test[2] + "]加密后为：" + en);
		 * System.out.println("字符串[" + en + "]解密后为：" + decrypt(en));
		 * System.out.println("字符串[" + test[0] + "]的长度为：" + getLength(test[0]));
		 * System.out.println("字符串[" + all + "]用[Company]替换[.com]后为：[" +
		 * replace(all, ".com", "Company") + "]");
		 * 
		 * String[] sp = split(test[0], "com"); System.out .println("字符串[" +
		 * test[0] + "]用[com]分隔为" + sp.length + "个字符串。分别为：[" + sp[0] + "],[" +
		 * sp[1] + "],[" + sp[2] + "]...");
		 * 
		 * System.out.println("字符串[" + test[1] + "]去掉左空格为：[" + trimLeft(test[1]) +
		 * "]"); System.out.println("字符串[" + test[1] + "]去掉右空格为：[" +
		 * trimRight(test[1]) + "]");
		 */		
		
		for (int i = 0; i < 5; i++) {
			System.out.println(StringUtil.randomStrPwd("9999", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", "`!@#$%^&**()-={}|:", 6, 3, 3, 0));
		}
	}	
	
	/**
	 * 随机生成给定长度的数字、大写字母、小写字母组合的字符串
	 * @param length 长度
	 * @return
	 */
	public static String randomStr(int length) {

		String upperStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		String lowerStr = "abcdefghijklmnopqrstuvwxyz";
		Random random = new Random();

		StringBuffer strbuffer = new StringBuffer(length);
		char[] u = upperStr.toCharArray();
		char[] l = lowerStr.toCharArray();
		for (int i = 0; i < length; i++) {
			int tmp = random.nextInt(3);
			if (tmp == 0) {
				strbuffer.append(u[random.nextInt(u.length)]);
			} else if (tmp == 1) {
				strbuffer.append(l[random.nextInt(l.length)]);
			} else {
				int k = random.nextInt();
				int j = Math.abs(k % 10);
				strbuffer.append(j);
			}
		}
		return strbuffer.toString();
	}
	
	/**
	 * 随机生成给定长度的 数字、大写字母、小写字母组合字符串
	 * @param intLength 数字位数
	 * @param upperStrLength 大写字母位数
	 * @param lowerStrLength 小写字母位数
	 * @return
	 */
	public static String randomStrAndInt(int intLength, int upperStrLength, int lowerStrLength) {

		String upperStrSource = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		String lowerStrSource = "abcdefghijklmnopqrstuvwxyz";
		char[] upperSource = upperStrSource.toCharArray();
		char[] lowerSource = lowerStrSource.toCharArray();
		
		Random random = new Random();
		List list = new ArrayList();
		
		//生成 intLength长度的整数字符串
		for (int i = 0; i < intLength; i++) {
			int k = random.nextInt();
			int j = Math.abs(k % 10);
			list.add(j);
		}
		
		//生成指定 upperStrLength 长度的大写字符串
		for (int i = 0; i < upperStrLength; i++) {
			list.add(upperSource[random.nextInt(upperSource.length)]);
		}
		
		//生成指定 lowerStrLength 长度的小写字符串
		for (int i = 0; i < lowerStrLength; i++) {
			list.add(lowerSource[random.nextInt(lowerSource.length)]);
		}
		Collections.shuffle(list); //随机排序
		StringBuffer strbuffer = new StringBuffer(list.size());
		for (int i = 0; i < list.size(); i++) {
			strbuffer.append(list.get(i));
		}
		return strbuffer.toString();
	}
	
	/**
	 * 随机生成给定长度的 数字、大写字母、小写字母、特殊字符的组合字符串
	 * @param upperStrSource
	 * @param lowerStrSource
	 * @param specialStrSource
	 * @param intLength
	 * @param upperLength
	 * @param lowerLength
	 * @param specialLength
	 * @return
	 */
	public static String randomStrPwd(String numberStrSource, String upperStrSource, String lowerStrSource, String specialStrSource, int intLength, int upperLength, int lowerLength, int specialLength) {

		char[] upperSource = upperStrSource.toCharArray();
		char[] lowerSource = lowerStrSource.toCharArray();
		char[] specialSource = specialStrSource.toCharArray();
		char[] numberSource = numberStrSource.toCharArray();
		
		Random random = new Random();
		List list = new ArrayList();
		
		//生成 intLength长度的整数字符串
		for (int i = 0; i < intLength; i++) {
			list.add(numberSource[random.nextInt(numberSource.length)]);
		}
		
		//生成指定 upperStrLength 长度的大写字符串
		for (int i = 0; i < upperLength; i++) {
			list.add(upperSource[random.nextInt(upperSource.length)]);
		}
		
		//生成指定 lowerStrLength 长度的小写字符串
		for (int i = 0; i < lowerLength; i++) {
			list.add(lowerSource[random.nextInt(lowerSource.length)]);
		}
		
		//生成指定 specialLength 长度的特殊字符
		for (int i = 0; i < specialLength; i++) {
			list.add(specialSource[random.nextInt(specialSource.length)]);
		}
		
		Collections.shuffle(list); //随机排序
		StringBuffer strbuffer = new StringBuffer(list.size());
		for (int i = 0; i < list.size(); i++) {
			strbuffer.append(list.get(i));
		}
		return strbuffer.toString();
	}
}
